package com.gc.server.service.impl;

import com.alibaba.excel.EasyExcel;
import com.gc.server.dao.LevelDao;
import com.gc.server.entity.*;
import com.gc.server.enums.LevelEnum;
import com.gc.server.enums.UserStatusEnum;
import com.gc.server.enums.UserVipEnum;
import com.gc.server.service.LinkHeadService;
import com.gc.server.service.PointTypeService;
import com.gc.server.service.ShopService;
import com.gc.server.vo.ShopVo;
import com.gc.server.vo.UserVo;
import com.gc.server.vo.down.ShopDown;
import com.gc.server.vo.down.UserDown;
import com.yf.response.RRException;
import com.yf.tz.common.Const;
import com.yf.tz.dao.ServerConfigDao;
import com.yf.tz.entity.ServerConfigEntity;
import com.yf.tz.service.AccountService;
import com.yf.tz.service.ServerConfigService;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

import com.gc.server.dao.UserDao;
import com.gc.server.service.UserService;
import com.yf.service.impl.BaseServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;

/**
 * 用户Service实现类
 *
 * @author hxf
 * @email 505860922@qq.com
 * @date Tue Mar 10 11:17:45 CST 2020
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<UserEntity> implements UserService {

    private UserDao userDao;

    private LevelDao levelDao;


    @Autowired
    public void setDao(UserDao userDao) {
        this.userDao = userDao;
        super.setBaseDao(userDao);
    }

    public LevelDao getLevelDao() {
        return levelDao;
    }

    @Autowired
    public void setLevelDao(LevelDao levelDao) {
        this.levelDao = levelDao;
    }


    @Override
    public List<UserVo> queryListVo(UserVo userVo) {
        return userDao.queryListVo(userVo);
    }

    @Override
    public UserVo getVo(Long id) {
        return userDao.getVo(id);
    }

    /**
     * 内部方法
     **/


    //生成编号
    private String createCode(String tCode) {
        Random random = new Random();
        String code = tCode + (random.nextInt(900000) + 100000);
        int count = 0;
        while (userDao.findByCode(code) != null) {
            count++;
            code = tCode + (random.nextInt(900000) + 100000);
            if (count > 5) {
                throw new RRException("生成代理编码失败");
            }
        }
        return code;
    }

    //团队
    private String createTeam(UserEntity topUser) {
        String team = topUser.getTeam() + topUser.getId() + "/";
        return team;
    }


    private void updateTeam(UserEntity user, UserEntity topUser) {
        String oldTeam = user.getTeam();
        String newTeam = user.getId() + "/";
        //设置Team
        if (topUser.getTeam() != null) {
            newTeam = topUser.getTeam() + newTeam;
        } else {
            newTeam = "/" + newTeam;
        }
        user.setTeam(newTeam);
        userDao.update(user);
        //更新下面团队的前缀
        if (oldTeam != null) {
            String oldTCode = user.getTCode();
            String newTCode = oldTCode;
            if (topUser.getTCode() != null) {
                newTCode = topUser.getTCode();
            }
            userDao.updateTeam(oldTCode, newTCode, oldTeam, newTeam);
        }
    }


    /**
     * 验证用户的基本信息
     *
     * @param userEntity
     */
    private void validateUser(UserEntity userEntity) {
        // 级别
        if (userEntity.getLevelId() == null) {
            throw new RRException("请选择注册的身份");
        }
        // 推荐人
        if (userEntity.getPid() == null) {
            throw new RRException("没有推荐人");
        }
        // 名字
        if (userEntity.getName() == null) {
            throw new RRException("填写名字");
        }
        // 手机号
        if (userEntity.getMobile() == null || userEntity.getMobile().trim().equals("")) {
            throw new RRException("请填写手机号码");
        }
        LevelEntity levelEntity = levelDao.get(userEntity.getLevelId());
        if (levelEntity.getName().equals(LevelEnum.BUS.getValue())) { //  业务员 终端
            // 银行卡
            if (userEntity.getBankNum() == null || userEntity.getBankNum().trim().equals("")) {
                throw new RRException("请填写银行卡号");
            }
            // 身份证
            if (userEntity.getIdCard() == null || userEntity.getIdCard().equals("")) {
                throw new RRException("请填写身份证号");
            }
            // 年龄
            if (userEntity.getAge() == null) {
                throw new RRException("请填写年龄");
            }
            // 性别
            if (userEntity.getSex() == null) {
                throw new RRException("请填写性别");
            }
            // 学历
            if (userEntity.getEdu() == null) {
                throw new RRException("请填写学历");
            }
            // 专业
            if (userEntity.getMajor() == null) {
                throw new RRException("请填写专业");
            }
            // 入职日期
            if (userEntity.getJoinDate() == null) {
                throw new RRException("请填写入职信息");
            }
        } else if (levelEntity.getName().equals(LevelEnum.SHOP.getValue())) { // 药店
            // 连锁药店名
            if (userEntity.getLinkName() == null || userEntity.getLinkName().trim().equals("")) {
                throw new RRException("请填写连锁药店名");
            }
            // 完整地址
            if (userEntity.getProvince() == null || userEntity.getDetail() == null || userEntity.getDetail().trim().equals("")) {
                throw new RRException("请完整填写地址");
            }
            // 药店名称
            if (userEntity.getShopName() == null || userEntity.getShopName().trim().equals("")) {
                throw new RRException("请填写药店名称");
            }
//            if(userEntity.getShopCode()==null||userEntity.getCode().trim().equals("")){
//                throw new RRException("请填写药店编号");
//            }
        }

    }


    /**
     * 外部方法实现
     **/


    @Override
    public UserEntity findByOpenId(String openId) {
        return userDao.findByOpenId(openId);
    }

    @Override
    public UserEntity findByWxId(String wxId) {
        return userDao.findByWxId(wxId);
    }

    /**
     * 业务员、药店注册、主管注册
     *
     * @param userEntity
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserEntity register(UserEntity userEntity) {
        if (userEntity.getPid() == null ) {
            throw new RRException("请推荐人二维码注册");
        }
        // 找出推荐人 验证推荐人信息
        UserEntity topUser = get(userEntity.getPid());
        if (topUser == null || topUser.getStatus().equals(UserStatusEnum.BAN.getIndex())) {
            throw new RRException("推荐人不存在!");
        }
        if(userEntity.getMobile()==null||userEntity.getName()==null||userEntity.getMobile().trim().length()<11){
            throw new RRException("手机号与姓名必填!");
        }
        //判断手机号是否重复
        UserEntity tem = userDao.findByMobile(userEntity.getMobile());
        if(tem!=null){
            throw new RRException("手机号已经注册:"+tem.getName());
        }
        String tCode = topUser.getTCode();
        String team = null; // 暂时不设置
        String code = createCode(tCode);
        //注册了未激活状态
        Integer status = UserStatusEnum.BAN.getIndex();
        //默认游客
        LevelEntity levelEntity = levelDao.get(0L);
        if(userEntity.getLevelId()!=null){
             levelEntity =  levelDao.get(userEntity.getLevelId());
        }
        if (levelEntity == null) {
            throw new RRException("请选择级别!");
        }
        UserEntity user;
        if (levelEntity.getName().equals(LevelEnum.BUS.getValue())) {
            // 业务员注册
            user = new UserEntity(userEntity.getName(), userEntity.getAvatar(), userEntity.getOpenId(), userEntity.getUnionId(), new Date(), userEntity.getMobile(), code, userEntity.getPid(), tCode, team, status, userEntity.getBankNum(), userEntity.getBankUser(), userEntity.getBankName(), userEntity.getBankBranch(), userEntity.getIdCard(), userEntity.getAge(), userEntity.getSex(), userEntity.getEdu(), userEntity.getMajor(), userEntity.getJoinDate(), userEntity.getLevelId());
        } else if (levelEntity.getName().equals(LevelEnum.SHOP.getValue())) {
            // 药店注册
            if(userEntity.getShopId()==null){
                throw new RRException("请选择对应的药店");
            }
            user = new UserEntity(userEntity.getName(), userEntity.getAvatar(), userEntity.getOpenId(), userEntity.getUnionId(), new Date(), userEntity.getMobile(), userEntity.getLevelId(), code, userEntity.getPid(), tCode, team, userEntity.getProvince(), userEntity.getCity(), userEntity.getCounty(), userEntity.getDetail(), status, userEntity.getLinkName(), userEntity.getShopName(), userEntity.getShopCode(), userEntity.getShopImg(), userEntity.getShopId(), userEntity.getBirth());
        } else {
            // 其他级别注册
            user = new UserEntity(userEntity.getName(), userEntity.getAvatar(), userEntity.getOpenId(), userEntity.getUnionId(), new Date(), userEntity.getMobile(), userEntity.getLevelId(), code, userEntity.getPid(), tCode, team, status, userEntity.getBankUser(), userEntity.getBankNum(), userEntity.getBankName(), userEntity.getBankBranch(), userEntity.getBirth());
        }
        //游客直接激活
        if(levelEntity.getName().equals(LevelEnum.CUSTOM.getValue())||levelEntity.getName().equals(LevelEnum.SHOP.getValue())){
            user.setStatus(UserStatusEnum.ACTIVE.getIndex());
        }
        //更新省市县
//        if(user.getProvince()==null||user.getProvince().equals("")){
//            user.setProvince(topUser.getProvince());
//            user.setCity(topUser.getCity());
//            user.setCounty(topUser.getCounty());
//        }
        //更新总部信息
        if(user.getShopId()!=null){
            ShopEntity shop = shopService.get(user.getShopId());
            user.setProvince(shop.getProvince());
            user.setCity(shop.getCity());
            user.setCounty(shop.getCounty());
            LinkHeadEntity head = headService.get(shop.getHead());
            if(head!=null){
                user.setLinkName(head.getName());
            }
        }
        //不可以兑费
        user.setVip(UserVipEnum.NO.getIndex());
        UserEntity temTop = userDao.get(topUser.getPid());
        user.setRemark("来源:"+topUser.getName()+"==>"+temTop.getName());
        userDao.save(user);
        updateTeam(user, topUser);
        //赠送积分
        PointTypeEntity pointTypeEntity =  pointTypeService.get(1L);
        if(pointTypeEntity!=null&&pointTypeEntity.getPoint()!=null){
            accountService.rewardPoint(user.getId(),pointTypeEntity.getPoint(),"注册赠送",null);
        }
        //记录上级
        return user;
    }

    @Autowired
    private LinkHeadService headService;

    @Autowired
    private ShopService shopService;

    @Autowired
    private AccountService accountService;

    @Autowired
    private PointTypeService pointTypeService;


    @Override
    public List<UserEntity> findMyShopUserAndLv(Long topId, Long levelId) {
        return userDao.findMyShopUserAndLevel(topId, levelId);
    }


    @Override
    public List<UserEntity> findMyShopUser(Long topId) {
        return userDao.findByPid(topId);
    }

    @Override
    public List<UserEntity> findChildren(Long topId) {
        topId = getAdmin(topId);
        List<UserEntity> list = userDao.findByPid(topId);
        findMyShopUsers(list, list.stream().map(UserEntity::getId).collect(Collectors.toList()), 0);
        return list;
    }

    void findMyShopUsers(List<UserEntity> list, List<Long> ids, Integer count) {
        //防止死循环
        count++;
        if (count > 30) {
            throw new RRException("用户层级错误ID");
        }
        if (list.size() <= 0) return;
        List<UserEntity> temps = userDao.findMyShopUsers(ids);
        if (temps.size() > 0) {
            list.addAll(temps);
            findMyShopUsers(list, temps.stream().map(UserEntity::getId).collect(Collectors.toList()), count);
        }
        return;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserEntity updateVo(UserVo userVo) {
        UserEntity userEntity = userVo.getUser();
        // 验证手机号
        if (userEntity.getMobile() != null) {
            UserEntity tem = userDao.findByMobile(userEntity.getMobile());
            if (tem != null && !tem.getId().equals(userEntity.getId())) {
                throw new RRException("手机号重复!");
            }
        }
        // 验证上级编号
        if (userVo.getTop() != null) {
            String topCode = userVo.getTop().getCode();
            if (topCode != null) {
                UserEntity topUser = userDao.findByCode(topCode);
                if (topUser == null) {
                    throw new RRException("上级编号有误!");
                }
                userEntity.setPid(topUser.getId());
                updateTeam(userEntity, topUser);
            }
        }

        if(userEntity.getShopId()!=null){
           ShopVo shop = shopService.getVo(userEntity.getShopId());
           userEntity.setShopName(shop.getShop().getShopName());
            userEntity.setProvince(shop.getEntity().getProvince());
            userEntity.setCity(shop.getEntity().getCity());
            userEntity.setCounty(shop.getEntity().getCounty());
           if(shop.getHead()!=null){
               userEntity.setLinkName(shop.getHead().getName());
           }
        }

        userDao.update(userEntity);
        return userEntity;
    }

    @Override
    public List<UserEntity> findByPidAndDate(Long pid, Date date) {
        return userDao.findByPidAndDate(pid, date);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserEntity register(Long pid, String unionId, String openId, String avatar, String name) {
//        LevelEntity levelEntity = levelDao.findBase();
        if (pid == null) {
            pid = Const.ADMIN_ID;
        }
        String code = createCode("V");
        UserEntity userEntity = new UserEntity(name, avatar, pid, 0L, new Date(), openId, unionId, code);
        userDao.save(userEntity);
        //赠送积分
        PointTypeEntity pointTypeEntity =  pointTypeService.get(1L);
        if(pointTypeEntity!=null&&pointTypeEntity.getPoint()!=null){
            accountService.rewardPoint(userEntity.getId(),pointTypeEntity.getPoint(),"注册赠送",null);
        }
        return userEntity;
    }

    @Override
    public List<Long> findTeam(Long userId) {
        List<Long> res = new ArrayList<>();
//        findTeam(userId, 0,res);
        List<UserEntity> users = findChildren(userId);
        res = users.stream().map(user->user.getId()).collect(Collectors.toList());
        return res;
    }

    @Autowired
    private ServerConfigService service;

    public Long getAdmin(Long userId) {
        //特殊定制一些特殊用户 能管理所有人的
        UserEntity userEntity = get(userId);
       ServerConfigEntity configEntity = service.findConfig();
        if (configEntity.getAdminCode()!=null&&configEntity.getAdminCode().contains(userEntity.getCode())) {
            userId = 0L;
        }
        return userId;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeVip(List<UserVo> userList) {
        for(UserVo userVo : userList){
            if(userVo.getUser().getVip()==null||userVo.getUser().getVip()==0){
                userVo.getUser().setVip(1);
            }else {
                userVo.getUser().setVip(0);
            }
            update(userVo.getUser());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserEntity act(Long userId, Long id) {
        UserEntity user = get(id);
        if(!user.getPid().equals(userId)){
            throw new RRException("只有直接上级能激活");
        }
        if(user.getLevelId()!=LevelEnum.SHOP.getIndex()&&user.getLevelId()!=LevelEnum.CUSTOM.getIndex()){
            throw new RRException("非管理员只能激活药店,客户");
        }
        if(user.getStatus().equals(UserStatusEnum.BAN.getIndex())){ //未激活激活
            user.setStatus(UserStatusEnum.ACTIVE.getIndex());
        }else {//已激活 给兑费
            user.setVip(UserVipEnum.YES.getIndex());
        }
        update(user);
        return user;
    }

    //递归查找整个团队的ID
    void findTeam(Long userId, Integer index, List<Long> res) {
        List<Long> ids = userDao.findByPid(userId).stream().map(user -> user.getId()).collect(Collectors.toList());
        if (ids.size() > 0) {
            res.addAll(ids);
            for (int i = 0; i < ids.size(); i++) {
                findTeam(ids.get(i), index, res);
            }
            index++;
            if (index > 50) {
                throw new RRException("层级关系异常");
            }
        }
    }

    @Override
    public List<UserEntity> sumByTop(Long userId, Date startDate, Date endDate, Long uid) {
        //找到所有下级
        List<Long> uids = findMyShopUser(userId).stream().map(UserEntity::getId).collect(Collectors.toList());
        //指定了UID
        if(uid!=null){
            uids = Arrays.asList(uid);
        }
        List<UserEntity> res = userDao.findMyShopUsers(uids);
        res = res.stream().filter(r->{
            if(startDate!=null&&endDate!=null){
                if(r.getRegisterTime().before(startDate)||r.getRegisterTime().after(endDate)){
                    return false;
                }
            }
            return true;
        }).collect(Collectors.toList());
        return res;
    }

    @Override
    public void downLoad(HttpServletResponse response, List<UserVo> list) {
        try {
            List<UserDown> datas = list.stream().map(item -> new UserDown(item)).collect(Collectors.toList());
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLE
            // ncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("测试", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream(), UserDown.class).sheet("模板").doWrite(datas);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
